package com.bpzj.drools.controller;

import com.bpzj.drools.entity.QueryParam;
import com.bpzj.drools.entity.RuleResult;
import com.bpzj.drools.service.CombineService;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import lombok.extern.slf4j.Slf4j;
import org.drools.compiler.kie.builder.impl.MemoryKieModule;
import org.drools.core.RuleBaseConfiguration;
import org.drools.core.impl.InternalKnowledgeBase;
import org.drools.core.impl.KnowledgeBaseFactory;
import org.drools.core.impl.KnowledgeBaseImpl;
import org.kie.api.KieBaseConfiguration;
import org.kie.api.KieServices;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.KieRepository;
import org.kie.api.builder.model.KieModuleModel;
import org.kie.api.definition.KiePackage;
import org.kie.api.io.ResourceType;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.internal.builder.KnowledgeBuilder;
import org.kie.internal.builder.KnowledgeBuilderFactory;
import org.kie.internal.io.ResourceFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/rule")
@Slf4j
public class RuleController {

  @Autowired
  private KieContainer kieContainer;
  @Autowired
  private KieFileSystem kieFileSystem;
  @Autowired
  private CombineService combineService;
  @Autowired
  private KieModuleModel kieModuleModel;
  @Autowired
  private KieRepository kieRepository;
  @Autowired
  private KieServices kieServices;


  @RequestMapping("/exe")
  public void test() {
    KieSession kieSession = kieContainer.newKieSession("session_rules.test");
    QueryParam queryParam1 = new QueryParam();
    queryParam1.setParamId("1");
    queryParam1.setParamSign("+");
    // 入参
    kieSession.insert(queryParam1);
    kieSession.insert(combineService);

    // 返参
    RuleResult resultParam = new RuleResult();
    kieSession.insert(resultParam);

//        kieFileSystem.delete("drools/param-check-one.drl");
    int rules = kieSession.fireAllRules();
    System.out.println("执行了" + rules + "条规则");
    kieSession.dispose();
  }

  /**
   * 更新一个规则
   */
  @RequestMapping("/update2")
  public void updateFile(String fileName) throws IOException {
    log.info("build file with filename {}", fileName);

    // 先更新 kieFileSystem
    // 封装成 drl 文件格式的内容
    String rule = "package newRules;\n"
        + "\n"
        + "import static com.bpzj.drools.service.CombineService.drlImport;\n"
        + "\n"
        + "dialect \"java\"\n"
        + "rule helloSomeone\n"
        + "    when\n"
        + "        eval( drlImport(\"Tom\"));\n"
        + "    then\n"
        + "        System.out.println(\"the param is not empty\");\n"
        + "    end";
    kieFileSystem.write("src/main/resources/newRules/test2.drl", rule);

    // 再更新 kieModuleModel
    String kBaseName = "kieBase_rules.test";
    String packageNameOfDrl = "newRules";
    String kieSessionName = "session_rules.test";
//    kieRepository.getKieModule(kieRepository.getDefaultReleaseId());
//    KieBaseModel kieBaseModel = kieModuleModel.newKieBaseModel(kBaseName);
//    kieBaseModel.addPackage(packageNameOfDrl);
//    kieBaseModel.newKieSessionModel(kieSessionName);
//    //这边主要目的是定义keyModel让不同的package对应不同的session，这样可以只触发某个session下的规则
//    kieFileSystem.writeKModuleXML(kieModuleModel.toXML());
//
//    // 最后 buildAll()
//    KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem).buildAll();
//
//    if (kieBuilder.getResults().hasMessages(Level.ERROR)) {
//      log.error("build rules error {}", kieBuilder.getResults().toString());
//    }

    // 不存在 KBase , 创建 KBase
    if (!kieContainer.getKieBaseNames().contains(kBaseName)) {
      // 1、使用 KnowledgeBuilder 得到 规则包 Collection<KiePackage>
      KnowledgeBuilder kb = KnowledgeBuilderFactory.newKnowledgeBuilder();
      // kb.add(ResourceFactory.newClassPathResource("Sample.drl"), ResourceType.DRL);
      kb.add(ResourceFactory.newByteArrayResource(rule.getBytes(StandardCharsets.UTF_8)), ResourceType.DRL);
      // 生成包, 编译成规则包
      Collection<KiePackage> knowledgePackages = kb.getKnowledgePackages();

      // 2、创建 KBase
      KieBaseConfiguration kbc = KnowledgeBaseFactory.newKnowledgeBaseConfiguration();
      kbc.setProperty("org.drools.sequential", "true");
      // 5、创建 kBase
      InternalKnowledgeBase kBase = KnowledgeBaseFactory.newKnowledgeBase(kbc);
      // 6、加入包
      kBase.addPackages(knowledgePackages);
      kBase.newKieSession();

      if (kb.hasErrors()) {
        String errorMessage = kb.getErrors().toString();
        System.out.println("规则语法异常---\n" + errorMessage);
      }

      // 创建新的 kbase
      MemoryKieModule kieModule = (MemoryKieModule) kieRepository.getKieModule(kieRepository.getDefaultReleaseId());

      RuleBaseConfiguration kieBaseConfiguration = (RuleBaseConfiguration) kieServices.newKieBaseConfiguration();
      kieBaseConfiguration.setProperty("name", kBaseName);
      kieContainer.newKieBase(kieBaseConfiguration);
//      kieContainer.newKieBase(kBaseName, kbc);

    } else {
      // 已经存在的 kBase 更新规则移除规则, 添加新规则
      //    kieBase.removeRule("rules","test");
      KnowledgeBaseImpl kieBase = (KnowledgeBaseImpl) kieContainer.getKieBase(kBaseName);
      //    kieBase.removeRule("rules", "test");
      //重新添加规则
      KnowledgeBuilder kb = KnowledgeBuilderFactory.newKnowledgeBuilder();
      //装入规则，可以装入多个
//      kb.add(ResourceFactory.newClassPathResource(rule.getBytes()), ResourceType.TDRL);
      kb.add(ResourceFactory.newByteArrayResource(rule.getBytes()), ResourceType.TDRL);
      kieBase.addPackages(kb.getKnowledgePackages());
    }
  }

  @RequestMapping("/delete")
  public void delete(String rule) throws IOException {
  }

}
